﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using umbraco.DataLayer;
using ub = umbraco.BusinessLogic;
using System.Web.UI.WebControls;
using umbraco.BusinessLogic;
namespace Core.Module.Controls
{
    public class LogViewer : UserControl
    {
        public const Int32 defAmount = 1000;
        public const Int32 deleteOlderThenDays = 750;

        public StringBuilder resLog;
        public StringBuilder ResLog
        {
            get
            {
                if (resLog == null) resLog = new StringBuilder();
                return resLog;
            }
        }

        public Int32 Amount
        {
            get
            {
                if (string.IsNullOrEmpty((Request["amount"] ?? "").Trim())) return defAmount;
                else
                {
                    Int32 resAmount;
                    if (Int32.TryParse(Request["amount"].Trim(), out resAmount)) return resAmount;
                    return defAmount;
                }
            }
        }
        /// <summary>
        /// list of fields which needs to be shown on a page
        /// </summary>
        private string[] ffields;
        public string[] Fields
        {
            get
            {
                if (ffields == null)
                {
                    string fields = !string.IsNullOrEmpty((Page.Request["chkResultFields"] ?? "").Trim())
                           ? Page.Request["chkResultFields"].Trim()
                           : "[id],[NodeId],[logComment],[logHeader],[userId],[datestamp]";
                    fields = fields.TrimStart('[').TrimEnd(']');
                    ffields = fields.Split(new string[] { "],[" }, StringSplitOptions.RemoveEmptyEntries);
                } return ffields;
            }
        }

        /// <summary>
        /// filter logs by: selLogCategory param
        /// </summary>
        public bool emptyFilterBy = false;
        public string FilterBy
        {
            get
            {
                if (emptyFilterBy) return "";
                return !string.IsNullOrEmpty((Page.Request["selLogCategory"] ?? "").Trim()) ? Page.Request["selLogCategory"].Trim() : "";
            }
        }

        /// <summary>
        /// Bind log items for an repeater
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void repLogs_Init(object sender, EventArgs e)
        {
            Repeater rep = sender as Repeater;
            if (rep != null)
            {
                rep.DataSource = GetFilteredLogItems();
                rep.DataBind();
            }
        }

        /// <summary>
        /// Bind log categories for an repeater
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void repCategories_Init(object sender, EventArgs e)
        {
            Repeater rep = sender as Repeater;
            if (rep != null)
            {
                rep.DataSource = Enum.GetNames(typeof(ub.LogTypes)).OrderBy(i => i);
                rep.DataBind();
            }
        }


        /// <summary>
        /// delete old logs by amount of days 
        /// </summary>
        /// <param name="olderThenThisDays"></param>
        public string DeleteOld()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("<p style='color:silver'>trying to delete logs older then -{0} days</p>", deleteOlderThenDays);
            string commandText = "delete from [dbo].[umbracolog] where datediff(day,datestamp,getdate())>" + deleteOlderThenDays.ToString();
            int amount = 0;
            try
            {
                IParameter dt = ub.Application.SqlHelper.CreateParameter("@longerthendays", deleteOlderThenDays);
                amount = ub.Application.SqlHelper.ExecuteNonQuery(commandText, new IParameter[] { dt });
                sb.AppendFormat("<p style='color:red'>{0}-items from log have been deleted</p>", amount);
            }
            catch (Exception ex)
            {
                sb.AppendFormat("<p style='color:red'>{0}<br/>{1}<br/>{2}</p>", ex.Message, ex.Source, ex.StackTrace);
                Log.Add(LogTypes.Error, -1, "can't delete old logitems by sql:" + commandText);
            }
            return amount > 0 ? sb.ToString() : "";
        }


        /// <summary>
        /// needs to return list of logitems 
        /// </summary>
        /// <returns></returns>
        public List<List<object>> GetFilteredLogItems()
        {
            List<List<object>> result = new List<List<object>>();
            string commandText = "select top " + Amount + " * from umbracoLog with(nolock)  where (id>0) {0} order by dateStamp desc";
            try
            {
                string whereText = string.IsNullOrEmpty(FilterBy) ? "" : string.Format("and (logHeader='{0}') ", FilterBy);
                whereText = string.IsNullOrEmpty(DateFilter) ? whereText : string.Format("{0} and (datestamp>@{1})", whereText, DateFilter);
                IRecordsReader logReader = ub.Application.SqlHelper.ExecuteReader(string.Format(commandText, whereText), GenerateParams(ub.Application.SqlHelper));
                if (logReader.HasRecords)
                {
                    int pos = 0;
                    ResLog.AppendFormat("<p>prepare log items...</p>");
                    List<object> hitem = new List<object>();
                    ResLog.AppendFormat("<p>generate head items</p>");
                    hitem.AddRange(Fields.AsEnumerable());
                    hitem.Add("Nr");
                    result.Add(hitem);
                    ResLog.AppendFormat("<p>done.</p>");
                    ResLog.AppendFormat("<p>generate items list</p>");
                    while (logReader.Read())
                    {
                        pos++;
                        List<object> item = new List<object>();
                        item.AddRange(
                            Fields.Select(f => logReader.GetObject(f))
                        );
                        item.Add(pos);
                        result.Add(item);
                    }
                    ResLog.AppendFormat("<p>done.Total:{0} -items</p>", pos);
                }
                else
                {
                    List<object> hitem = new List<object>();
                    hitem.Add("<p style='color:blue;'>no log items have been found!</p>");
                    result.Add(hitem);
                }
            }
            catch (Exception ex)
            {
                ResLog.AppendFormat("<p style='color:red'>{3} {0}<br/>{1}<br/>{2}</p>", ex.Message, ex.Source, ex.StackTrace,ex.InnerException!=null?ex.InnerException.Message:"");
                Log.Add(LogTypes.Error, -1, "Can't show log items! En error:" + ex.Message + ex.Source + ex.StackTrace);
                List<object> hitem = new List<object>();
                hitem.Add("<p style='color:red;'>" + ex.Message + "</p>");
                result.Add(hitem);
            }
            return result;
        }

        private IParameter[] GenerateParams(ISqlHelper sqlHelper)
        {
            List<IParameter> rslt = new List<IParameter>();
            //dates
            rslt.Add(sqlHelper.CreateParameter("@today", DateTime.Today));
            rslt.Add(sqlHelper.CreateParameter("@day1", DateTime.Today.AddDays(-1)));
            rslt.Add(sqlHelper.CreateParameter("@day2", DateTime.Today.AddDays(-2)));
            rslt.Add(sqlHelper.CreateParameter("@day3", DateTime.Today.AddDays(-3)));
            rslt.Add(sqlHelper.CreateParameter("@week1", DateTime.Today.AddDays(-7)));
            rslt.Add(sqlHelper.CreateParameter("@week2", DateTime.Today.AddDays(-14)));
            rslt.Add(sqlHelper.CreateParameter("@month1", DateTime.Today.AddDays(-30)));
            rslt.Add(sqlHelper.CreateParameter("@quarter1", DateTime.Today.AddDays(-90)));
            rslt.Add(sqlHelper.CreateParameter("@year1", DateTime.Today.AddYears(-1)));
            return rslt.ToArray();
        }

        protected override void OnInit(EventArgs e)
        {
            if ((Request["deletefiltered"] ?? "").Equals("1")) DeleteFilteredValues();
            base.OnInit(e);
        }


        public void DeleteFilteredValues()
        {
            emptyFilterBy = false;
            string whereText = string.IsNullOrEmpty(FilterBy) ? "" : string.Format("and (logHeader='{0}') ", FilterBy);
            whereText = string.IsNullOrEmpty(DateFilter) ? whereText : string.Format("{0} and (datestamp>@{1})", whereText, DateFilter);
            if (!string.IsNullOrEmpty(whereText))
            {
                ResLog.AppendFormat("<p style='color:silver'>trying to delete logs by logHeader</p>");
                string commandText = string.Format("delete from [dbo].[umbracolog] where (id>0) {0}", whereText);
                try
                {
                    int amount = ub.Application.SqlHelper.ExecuteNonQuery(commandText, GenerateParams(ub.Application.SqlHelper));
                    ResLog.AppendFormat("<p style='color:red'>{0}-items from log have been deleted</p>", amount);
                    if (amount > 0)
                    {
                        ResLog.AppendLine("<script type='text/javascript'>UmbClientMgr.mainTree().refreshTree();</script>");
                    }
                    Log.Add(LogTypes.Notify,-2, amount.ToString() + "- items have been deleted from log by category:" + FilterBy + ", for time period:" + DateFilter);
                    emptyFilterBy = true;
                }
                catch (Exception ex)
                {
                    ResLog.AppendFormat("<p style='color:red'>{0}<br/>{1}<br/>{2}</p>", ex.Message, ex.Source, ex.StackTrace);
                    Log.Add(LogTypes.Error, -1, "Couldn't clear log information by query:" + commandText);
                }
            } else Log.Add(LogTypes.Notify, -1, "Can't clear log storage the filter hasn't been specified (date or category)!");
        }




        public string DateFilter
        {
            get
            {
                string param = (Request.Form["period"] ?? "").Trim();
                param = string.IsNullOrEmpty(param) ? (Request["period"] ?? "").Trim() : param;//get from query string too
                if (string.IsNullOrEmpty(param)) return "";
                if ("today".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "today";
                if ("day1".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "day1";
                if ("day2".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "day2";
                if ("day3".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "day3";
                if ("week1".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "week1";
                if ("month1".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "month1";
                if ("quarter1".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "quarter1";
                if ("year1".Equals(param, StringComparison.InvariantCultureIgnoreCase)) return "year1";
                return "";
            }
        }
    }
}
